[チュートリアル] Amazon SQSメッセージを処理するLambda関数を作成してみた
こんにちは、CX事業本部 IoT事業部の若槻です。
Amazon SQSは、AWS上で疎結合でスケーラブルなシステムを実装するのに役立つフルマネージド型のメッセージキューイングサービスです。
しかし私は今までAmazon SQSを使う機会がなかなか無く、いい加減触ってみようかなと思っていたところ、ちょうど良さそうなチュートリアルを見つけたので、今回やってみました。
やってみた
やってみたのは、次のAmazon SQSメッセージを処理するLambda関数を作成するチュートリアルです。
実行ロールを作成する
Lambda関数実行用のIAMロールを作成します。
https://console.aws.amazon.com/iam/home#/roles を開き、[ロールの作成]をクリック。
[信頼されたエンティティ]でAWS サービス
、[ユースケースの選択]でLambda
を選択し、[次のステップ]をクリック。
AWSLambdaSQSQueueExecutionRole
を選択し、[次のステップ]をクリック。
ちなみにAWSLambdaSQSQueueExecutionRole
のポリシーの概要は次のようになります。Lambda関数がSQSメッセージを読み取り、CloudWatch Logsにログを書き込むためのアクセス許可です。
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "sqs:ReceiveMessage", "sqs:DeleteMessage", "sqs:GetQueueAttributes", "logs:CreateLogGroup", "logs:CreateLogStream", "logs:PutLogEvents" ], "Resource": "*" } ] }
[タグの追加]では何もせずに[次のステップ]をクリック。
[確認]では、[ロール名]でlambda-sqs-role
を指定して、[ロールの作成]をクリック。
作成できました。
関数を作成する
Node.jsランタイムで実行可能なLambda関数のハンドラーコードindex.js
を次の通り作成します。
exports.handler = async function(event, context) { event.Records.forEach(record => { const { body } = record; console.log(body); }); return {}; }
デプロイパッケージを作成します。
$ zip function.zip index.js
AWS CLIのlambda create-function
コマンドを実行してLambda関数を作成します。
$ ACCOUNT_ID=<アカウントID> $ aws lambda create-function \ --function-name ProcessSQSRecord \ --zip-file fileb://function.zip \ --handler index.handler \ --runtime nodejs12.x \ --role arn:aws:iam::${ACCOUNT_ID}:role/lambda-sqs-role
マネジメントコンソールを見るとLambda関数がちゃんと作成されています。
関数をテストする
次のSQSメッセージのレコードを記載したinput.txt
ファイルを作成します。
{ "Records": [ { "messageId": "059f36b4-87a3-44ab-83d2-661975830a7d", "receiptHandle": "AQEBwJnKyrHigUMZj6rYigCgxlaS3SLy0a...", "body": "test", "attributes": { "ApproximateReceiveCount": "1", "SentTimestamp": "1545082649183", "SenderId": "AIDAIENQZJOLO23YVJ4VO", "ApproximateFirstReceiveTimestamp": "1545082649185" }, "messageAttributes": {}, "md5OfBody": "098f6bcd4621d373cade4e832627b4f6", "eventSource": "aws:sqs", "eventSourceARN": "arn:aws:sqs:ap-northeast-1:123456789012:my-queue", "awsRegion": "ap-northeast-1" } ] }
lambda invoke
コマンドを次の通り実行します。するとInvalid base64
というエラーとなりました。
$ aws lambda invoke \ --function-name ProcessSQSRecord \ --payload file://input.txt outputfile.txt Invalid base64: "{ "Records": [ { "messageId": "059f36b4-87a3-44ab-83d2-661975830a7d", "receiptHandle": "AQEBwJnKyrHigUMZj6rYigCgxlaS3SLy0a...", "body": "test", "attributes": { "ApproximateReceiveCount": "1", "SentTimestamp": "1545082649183", "SenderId": "AIDAIENQZJOLO23YVJ4VO", "ApproximateFirstReceiveTimestamp": "1545082649185" }, "messageAttributes": {}, "md5OfBody": "098f6bcd4621d373cade4e832627b4f6", "eventSource": "aws:sqs", "eventSourceARN": "arn:aws:sqs:ap-northeast-1:123456789012:my-queue", "awsRegion": "ap-northeast-1" } ] } "
なるほどAWS CLI v2を使っている場合はペイロードをBase64エンコードする必要があるんですね。
簡単にまとめれば、バイナリパラメーター(blob)を指定する際にはBase64でエンコードしてね、ということです。lambda invokeの--payloadはblobで指定することになっています。そのためAWS CLI v2ではペイロードをBase64でエンコードする必要があるわけです。それでは実例も交えて確認してみましょう。
作業環境のAWS CLIバージョンを確認するとV2です。なのでBase64エンコードが必要です。
$ aws --version aws-cli/2.0.28 Python/3.7.4 Darwin/20.6.0 botocore/2.0.0dev32
今回はとりあえずの回避策としてマネジメントコンソールからテストをしてみます。
実行できました。関数がSQSのメッセージのレコードを処理できています。
Amazon SQS キュー を作成する
Amazon SQS コンソールを開き、[キューを作成]をクリック。
ここでキューの設定が色々出来るのですが、標準キューで[名前]をMyQueue
と指定し、
[キューを作成]をクリック。
キューを作成できました。このキューのARNを控えます。
イベントソースを設定する
先程のARNを指定して、create-event-source-mapping
コマンドを次の通り実行します。これによりAmazon SQS キューと Lambda 関数の間イベントソースマッピングを設定します。
$ QUEUE_ARN=<キューのARN> $ aws lambda create-event-source-mapping \ --function-name ProcessSQSRecord \ --batch-size 10 \ --event-source-arn ${QUEUE_ARN}
動作確認
先程作成したキューの詳細ページで[メッセージを送受信]をクリック。
[メッセージ本文]を指定して、[メッセージを送信]をクリックしキューメッセージを送信します。
Lambda関数のCloudWatch Logsのログイベントを見ると、キューメッセージを受信していることを確認できました!
おわりに
Amazon SQSメッセージを処理するLambda関数を作成するチュートリアルをやってみました。
Amazon SQSに関して今までは認定試験の勉強で仕様や実装パターンを覚えるだけの机上の知識しかありませんでしたが、今回触ってみて何となくの雰囲気がつかめました。
以上